package org.nvm.core;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

import org.nvm.cfg.DictConfiguration;
import org.nvm.util.CharacterUtils;
/**
 * 分词过程上下文
 * @author ThinkPad
 *
 */
public class AnalyzeContext {
	
	private static final int BUFF_SIZE = 4096;
	private static final int BUFF_CRITICAL_EXHAUST = 64;
	
	private volatile char[] segmentBuff;
	private int[] charTypes;
	
	private int buffOffset;
	private int cursor;
	private int available;
	
	private Set<String> buffLocker;
	
	private QuickSortSet orgLexemes;
	
	private Map<Integer, LexemePath> pathMap;
	
	private LinkedList<Lexeme> results;
	
	private DictConfiguration cfg;
	
	public AnalyzeContext(DictConfiguration cfg) {
		this.cfg = cfg;
		this.segmentBuff = new char[BUFF_SIZE];
		this.charTypes = new int[BUFF_SIZE];
		this.buffLocker = new HashSet<>();
		this.orgLexemes = new QuickSortSet();
		this.pathMap = new HashMap<>();
		this.results = new LinkedList<>();
	}
	int cursor() {
		return this.cursor;
	}
	char[] getSegmentBuff() {
		return this.segmentBuff;
	}
	
	char getCurrentChar() {
		return this.segmentBuff[this.cursor];
	}
	int getCurrentCharType() {
		return this.charTypes[this.cursor];
	}
	
	int getBuffOffset() {
		return this.buffOffset;
	}
	
	int fillBuffer(Reader reader) throws IOException {
		int readCount = 0;
		
		if(this.buffOffset == 0) {
			try {
				readCount = reader.read(segmentBuff);
			} catch (Exception e) {
				return 0;
			}
		} else {
			//剩余未处理
			int offset = this.available - this.cursor;
			
			if(offset > 0) {
				System.arraycopy(this.segmentBuff, this.cursor, this.segmentBuff, 0, offset);
				readCount = offset;
			}
			
			readCount += reader.read(this.segmentBuff, offset, BUFF_SIZE - offset);
		}
		
		this.available = readCount;
		
		this.cursor = 0;
		
		return readCount;
	}
	
	public void initCursor() {
		this.cursor = 0;
		setCharAndType();
	}
	
	boolean stepCursor() {
		if(this.cursor < this.available - 1) {
			this.cursor ++;
			setCharAndType();
			return true;
		}
		return false;
	}
	private void setCharAndType() {
		this.segmentBuff[this.cursor] = CharacterUtils.normalized(this.segmentBuff[this.cursor]);
		this.charTypes[this.cursor] = CharacterUtils.normalized(this.segmentBuff[this.cursor]);
	}
	
	void lockBuffer(String segName) {
		this.buffLocker.add(segName);
	}
	void unlockBuffer(String segName) {
		this.buffLocker.remove(segName);
	}
	boolean isBufferLocked() {
		return this.buffLocker.size() > 0;
	}
	boolean isBufferConsumed() {
		return this.cursor == this.available - 1;
	}
	
	boolean neadReadBuffer() {
		return this.available == BUFF_SIZE
				&& this.cursor < this.available - 1
				&& this.cursor > this.available - BUFF_CRITICAL_EXHAUST
				&& !this.isBufferLocked();
	}
	
	void markBufferOffset() {
		this.buffOffset += this.cursor;
	}
	void addLexeme(Lexeme lexeme) {
		this.orgLexemes.addLexeme(lexeme);
	}
	
	void addLexemePath(LexemePath path) {
		if(path != null) {
			this.pathMap.put(path.getPathBegin(), path);
		}
	}
	/**
	 * 返回原始的分词结果
	 * @return
	 */
	QuickSortSet getOrgLexemes() {
		return this.orgLexemes;
	}
	
	void processUnknowCJKChar() {
		int index = 0;
		for( ; index < this.available ;){
			//跳过标点符号等字符
			if(CharacterUtils.CHAR_USELESS == this.charTypes[index]){
				index++;
				continue;
			}
			//从pathMap找出对应index位置的LexemePath
			LexemePath path = this.pathMap.get(index);
			if(path != null){
				//输出LexemePath中的lexeme到results集合
				Lexeme l = path.shiftHead();
				while(l != null){
					this.results.add(l);
					//将index移至lexeme后
					index = l.getBegin() + l.getLength();					
					l = path.shiftHead();
					if(l != null){
						//输出path内部，词元间遗漏的单字
						for(;index < l.getBegin();index++){
							this.outputSingleCJK(index);
						}
					}
				}
			}else{//pathMap中找不到index对应的LexemePath
				//单字输出
				this.outputSingleCJK(index);
				index++;
			}
		}
		//清空当前的Map
		this.pathMap.clear();
	}
	private void outputSingleCJK(int index){
		if(CharacterUtils.CHAR_CHINESE == this.charTypes[index]){			
			Lexeme singleCharLexeme = new Lexeme(this.buffOffset , index , 1 , Lexeme.TYPE_CNCHAR);
			this.results.add(singleCharLexeme);
		}else if(CharacterUtils.CHAR_OTHER_CJK == this.charTypes[index]){
			Lexeme singleCharLexeme = new Lexeme(this.buffOffset , index , 1 , Lexeme.TYPE_OTHER_CJK);
			this.results.add(singleCharLexeme);
		}
	}
	
	/**
	 * 判断结果集中是否还有为输出的结果
	 * @return
	 */
	boolean hasNextResult(){
		return !this.results.isEmpty();
	}
	
	/**
	 * 返回lexeme 
	 * 
	 * 同时处理合并
	 * @return
	 */
	Lexeme getNextLexeme(){
		//从结果集取出，并移除第一个Lexme
		Lexeme result = this.results.pollFirst();
//		while(result != null){
//    		//数量词合并
//    		this.compound(result);
//    		if(Dictionary.getSingleton().isStopWord(this.segmentBuff ,  result.getBegin() , result.getLength())){
//       			//是停止词继续取列表的下一个
//    			result = this.results.pollFirst(); 				
//    		}else{
//	 			//不是停止词, 生成lexeme的词元文本,输出
//	    		result.setLexemeText(String.valueOf(segmentBuff , result.getBegin() , result.getLength()));
//	    		break;
//    		}
//		}
//		return result;

		if(result != null)
		{
			this.compound(result);
			result.setLexemeText(String.valueOf(segmentBuff , result.getBegin() , result.getLength()));
		}
		return result;
	}
	
	/**
	 * 重置分词上下文状态
	 */
	void reset(){		
		this.buffLocker.clear();
        this.orgLexemes = new QuickSortSet();
        this.available =0;
        this.buffOffset = 0;
    	this.charTypes = new int[BUFF_SIZE];
    	this.cursor = 0;
    	this.results.clear();
    	this.segmentBuff = new char[BUFF_SIZE];
    	this.pathMap.clear();
	}
	
	/**
	 * 组合词元
	 */
	private void compound(Lexeme result){
		if(!this.cfg.useSmart()){
			return ;
		}
   		//数量词合并处理
		if(!this.results.isEmpty()){

			if(Lexeme.TYPE_ARABIC == result.getType()){
				Lexeme nextLexeme = this.results.peekFirst();
				boolean appendOk = false;
				if(Lexeme.TYPE_CNUM == nextLexeme.getType()){
					//合并英文数词+中文数词
					appendOk = result.append(nextLexeme, Lexeme.TYPE_CNUM);
				}else if(Lexeme.TYPE_COUNT == nextLexeme.getType()){
					//合并英文数词+中文量词
					appendOk = result.append(nextLexeme, Lexeme.TYPE_CQUAN);
				}
				if(appendOk){
					//弹出
					this.results.pollFirst(); 
				}
			}
			
			//可能存在第二轮合并
			if(Lexeme.TYPE_CNUM == result.getType() && !this.results.isEmpty()){
				Lexeme nextLexeme = this.results.peekFirst();
				boolean appendOk = false;
				 if(Lexeme.TYPE_COUNT == nextLexeme.getType()){
					 //合并中文数词+中文量词
 					appendOk = result.append(nextLexeme, Lexeme.TYPE_CQUAN);
 				}  
				if(appendOk){
					//弹出
					this.results.pollFirst();   				
				}
			}

		}
	}
}
